package com.tanhua.server.service;


import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Visitors;
import com.tanhua.domain.vo.MovementsVo;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.VisitorsVo;
import com.tanhua.dubbo.api.PublishApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.RelativeDateFormat;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @Reference
    private PublishApi publishApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Reference
    private VisitorsApi visitorsApi;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private MovementsMQService movementsMQService;

    /**
     * 接口名称：动态-发布
     */
    public ResponseEntity<Object> saveMovements(Publish publish, MultipartFile[] imageContent) throws Exception {
        // 1.上传图片到阿里云oss
        List<String> urlList = new ArrayList<>();
        if (imageContent != null) {
            for (MultipartFile multipartFile : imageContent) {
                String url = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
                urlList.add(url);
            }
        }
        // 2.设置相关参数
        publish.setMedias(urlList);
        publish.setUserId(UserHolder.getUserId());
        publish.setCreated(System.currentTimeMillis());

        // 3.调用服务提供者api保存动态
        publish.setId(ObjectId.get()); // 生成id
        publish.setState(0); // 状态未审核
        publishApi.save(publish);

        // 【动态审核消息，发送到RocketMQ】
        rocketMQTemplate.convertAndSend("tanhua-publish", publish.getId().toString());
        // 【发送评分消息到RocketMQ】
        movementsMQService.sendMsg(publish.getId().toString(), 1);

        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：好友动态
     */
    public ResponseEntity<Object> queryPublishList(Integer page, Integer pagesize) {
        // 1.获取当前登录用户id
        Long userId = UserHolder.getUserId();

        // 2.调用服务提供者api分页查询动态列表
        PageResult pageResult = publishApi.findByTimeLine(userId, page, pagesize);

        // 3.调用公共方法设置pageResult
        setMovementsVo(pageResult);

        return ResponseEntity.ok(pageResult);
    }

    /**
     * 接口名称：推荐动态
     */
    public ResponseEntity<Object> queryRecommendPublishList(Integer page, Integer pagesize) {
        // 1.获取当前登录用户id
        Long userId = UserHolder.getUserId();

        // 2.查询redis的推荐数据
        PageResult pageResult = findByRecommend(userId, page, pagesize);

        if (pageResult == null) {
            // 2.1 如果redis推荐数据不存在，再调用服务提供者api分页查询动态列表
            pageResult = publishApi.queryRecommendPublishList(userId, page, pagesize);
        }

        // 3.调用公共方法设置pageResult
        setMovementsVo(pageResult);

        return ResponseEntity.ok(pageResult);
    }

    /**
     * 查询redis中的推荐动态数据
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    private PageResult findByRecommend(Long userId, Integer page, Integer pagesize) {
        // 1.拼接key
        String key = "QUANZI_PUBLISH_RECOMMEND_" + userId;

        // 2.查询redis的推荐动态pid
        String value = redisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        // 3.将value转为数组，22,20,29,33,7,36,36,14,38,19
        String[] pids = value.split(",");
        // 将pids转为list集合
        List<Long> pidList = new ArrayList<>();
        for (String pid : pids) {
            pidList.add(Long.valueOf(pid));
        }

        // 4.调用服务提供者api，分页查询动态列表
        PageResult pageResult = publishApi.findByIds(pidList, page, pagesize);

        return pageResult;
    }


    /**
     * 好友动态及推荐动态公共方法
     *
     * @param pageResult
     */
    private void setMovementsVo(PageResult pageResult) {

        // 获取当前页的数据
        List<Publish> publishList = (List<Publish>) pageResult.getItems();

        // 3.封装返回结果
        List<MovementsVo> voList = new ArrayList<>();
        if (publishList != null) {
            for (Publish publish : publishList) {
                // 3.1 创建vo
                MovementsVo vo = new MovementsVo();

                // 3.2 封装数据：动态信息
                BeanUtils.copyProperties(publish, vo);
                // 封装图片url
                if (publish.getMedias() != null) {
                    String[] imageContent = publish.getMedias().toArray(new String[]{});
                    vo.setImageContent(imageContent);
                }

                // 3.3 封装数据：用户详情
                UserInfo userInfo = userInfoApi.findById(publish.getUserId());
                if (userInfo != null) {
                    BeanUtils.copyProperties(userInfo, vo);
                    // 转换标签
                    if (!StringUtils.isEmpty(userInfo.getTags())) {
                        String[] tags = userInfo.getTags().split(",");
                        vo.setTags(tags);
                    }
                }

                // 3.4 封装其他属性
                vo.setId(publish.getId().toString());
                vo.setDistance("50米");
                // 格式化日期，将年月日转为xxx小时前
                vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

                // 3.5 从redis查询用户点赞动态的标记
                String likeKey = "public_like_comment_" + UserHolder.getUserId() + "_" + vo.getId();
                if (redisTemplate.hasKey(likeKey)) {
                    // 如果存在标记，即用户点赞过该动态
                    vo.setHasLiked(1);
                } else {
                    vo.setHasLiked(0);
                }

                // 获取redis存储的当前用户的喜欢标记
                String loveKey = "public_love_comment_" + UserHolder.getUserId() + "_" + vo.getId();
                if (redisTemplate.hasKey(loveKey)) {
                    vo.setHasLoved(1);
                } else {
                    vo.setHasLoved(0);
                }


                // 3.6 添加vo到集合
                voList.add(vo);
            }
        }

        // 4.重新设置items的值
        pageResult.setItems(voList);
    }

    /**
     * 接口名称：单条动态
     */
    public ResponseEntity<Object> queryMovementsById(String id) {

        // 1.调用服务提供者api查询动态详情
        Publish publish = publishApi.findById(id);

        // 2.封装返回结果
        MovementsVo vo = new MovementsVo();

        // 2.1 封装数据：动态信息
        BeanUtils.copyProperties(publish, vo);
        // 封装图片url
        if (publish.getMedias() != null) {
            String[] imageContent = publish.getMedias().toArray(new String[]{});
            vo.setImageContent(imageContent);
        }

        // 2.2 封装数据：用户详情
        UserInfo userInfo = userInfoApi.findById(publish.getUserId());
        if (userInfo != null) {
            BeanUtils.copyProperties(userInfo, vo);
            // 转换标签
            if (!StringUtils.isEmpty(userInfo.getTags())) {
                String[] tags = userInfo.getTags().split(",");
                vo.setTags(tags);
            }
        }

        // 2.3 封装其他属性
        vo.setId(publish.getId().toString());
        vo.setDistance("50米");
        // 格式化日期，将年月日转为xxx小时前
        vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));

        // 2.4 从redis查询用户点赞动态的标记
        String likeKey = "public_like_comment_" + UserHolder.getUserId() + "_" + vo.getId();
        if (redisTemplate.hasKey(likeKey)) {
            // 如果存在标记，即用户点赞过该动态
            vo.setHasLiked(1);
        } else {
            vo.setHasLiked(0);
        }

        // 获取redis存储的当前用户的喜欢标记
        String loveKey = "public_love_comment_" + UserHolder.getUserId() + "_" + vo.getId();
        if (redisTemplate.hasKey(loveKey)) {
            vo.setHasLoved(1);
        } else {
            vo.setHasLoved(0);
        }

        return ResponseEntity.ok(vo);
    }

    /**
     * 接口名称：谁看过我
     *
     * @return
     */
    public ResponseEntity<Object> queryVisitors() {
        // 1.拼接redis中的key
        String key = "visitor_time_" + UserHolder.getUserId();

        List<Visitors> visitorsList = null;

        // 1.1 判断key是否存在
        if (!redisTemplate.hasKey(key)) {
            // 1.2 说明是第一次进入首页，查询访客表前5条数据
            visitorsList = visitorsApi.queryVisitors(UserHolder.getUserId(), 5);

        } else {
            // 1.3 说明不是第一次
            // 获取上一次进入首页的时间
            Long lastTime = Long.valueOf(redisTemplate.opsForValue().get(key));
            visitorsList = visitorsApi.queryVisitors(UserHolder.getUserId(), lastTime);
        }

        // 2.记录本次进入首页的时间
        redisTemplate.opsForValue().set(key, System.currentTimeMillis() + "");

        // 3.封装返回结果
        List<VisitorsVo> voList = new ArrayList<>();

        if (visitorsList != null) {

            for (Visitors visitors : visitorsList) {
                // 3.1 创建vo
                VisitorsVo vo = new VisitorsVo();

                // 3.2 查询访客的用户详情，并封装
                UserInfo userInfo = userInfoApi.findById(visitors.getVisitorUserId());
                if (userInfo != null) {
                    BeanUtils.copyProperties(userInfo, vo);
                    if (userInfo.getTags() != null) {
                        vo.setTags(userInfo.getTags().split(","));
                    }
                }
                vo.setFateValue(visitors.getScore().intValue());
                vo.setId(visitors.getVisitorUserId());

                // 3.3 添加vo到集合
                voList.add(vo);
            }
        }

        return ResponseEntity.ok(voList);
    }

    /**
     * 我的动态
     * @param page 当前页
     * @param pagesize 当前页大小
     * @param userId 用户Id
     * @return
     */
    public ResponseEntity<Object> queryMyPublishList(Integer page, Integer pagesize, Long userId) {
        // 1.获取登录用户id
        if (userId == null) {
            // 如果未传入userId，就获取当前用户id
            userId = UserHolder.getUserId();
        }

        // 2.调用服务提供者分页查询该用户的个人动态
        PageResult pageResult = publishApi.queryMyPublishList(page, pagesize, userId);

        // 3.调用公共方法，设置返回结果
        setMovementsVo(pageResult);

        return ResponseEntity.ok(pageResult);
    }
}
